#ifndef __OCPP_CesiumSpherical_H__
#define __OCPP_CesiumSpherical_H__

#include "CesiumDef.h"

namespace OCPP
{
	namespace Cesium
	{
		class _CesiumExport Spherical
		{
		public:
			double clock, cone, magnitude;
			Spherical(double _clock = 0.0, double _cone = 0.0, double _magnitude = 0.0)
				: clock(_clock)
				, cone(_cone)
				, magnitude(_magnitude)
			{

			}

			static Spherical fromCartesian3(Cartesian3 cartesian3);

			static Spherical normalize(Spherical spherical) {
				Spherical result = Spherical(spherical.clock, spherical.cone, 1.0);
				result.clock = spherical.clock;
				result.cone = spherical.cone;
				result.magnitude = 1.0;
				return result;
			};

			/**
			 * Returns true if the first spherical is equal to the second spherical, false otherwise.
			 *
			 * @param {Spherical} left The first Spherical to be compared.
			 * @param {Spherical} right The second Spherical to be compared.
			 * @returns {boolean} true if the first spherical is equal to the second spherical, false otherwise.
			 */
			static bool equals(Spherical& left, Spherical& right) {
				return
					left.clock == right.clock &&
					left.cone == right.cone &&
					left.magnitude == right.magnitude
					;
			};

			/**
			 * Returns true if the first spherical is within the provided epsilon of the second spherical, false otherwise.
			 *
			 * @param {Spherical} left The first Spherical to be compared.
			 * @param {Spherical} right The second Spherical to be compared.
			 * @param {number} [epsilon=0.0] The epsilon to compare against.
			 * @returns {boolean} true if the first spherical is within the provided epsilon of the second spherical, false otherwise.
			 */
			static bool equalsEpsilon(Spherical& left, Spherical& right, double epsilon = 0.0) {
				return
					abs(left.clock - right.clock) <= epsilon &&
					abs(left.cone - right.cone) <= epsilon &&
					abs(left.magnitude - right.magnitude) <= epsilon
					;
			};

			/**
			 * Returns true if this spherical is equal to the provided spherical, false otherwise.
			 *
			 * @param {Spherical} other The Spherical to be compared.
			 * @returns {boolean} true if this spherical is equal to the provided spherical, false otherwise.
			 */
			bool equals(Spherical& other) {
				return Spherical::equals(*this, other);
			};

			/**
			 * Returns true if this spherical is within the provided epsilon of the provided spherical, false otherwise.
			 *
			 * @param {Spherical} other The Spherical to be compared.
			 * @param {number} epsilon The epsilon to compare against.
			 * @returns {boolean} true if this spherical is within the provided epsilon of the provided spherical, false otherwise.
			 */
			bool equalsEpsilon(Spherical& other, double epsilon) {
				return Spherical::equalsEpsilon(*this, other, epsilon);
			};

			/**
			 * Returns a string representing this instance in the format (clock, cone, magnitude).
			 *
			 * @returns {string} A string representing this instance.
			 */
			String toString() {
				return str_format("%f,%f,%f", clock, cone, magnitude);
			};
		};
	}
}
#endif

